#include <iostream>
using namespace std;

class Prototype {
protected:
    int value = 0;
    string name = "Blue";

public:
    void setValue(int value) {
        Prototype::value = value;
    }

    void setName(const string &name) {
        Prototype::name = name;
    }

    virtual void printf() = 0;

    virtual Prototype *clone() = 0;
};

class ConcretePrototypeA : public Prototype {
public:
    void printf() override {
        cout << "Concrete Prototype A!" << endl;
        cout << "Prototype name = " << name << endl;
        cout << "Prototype value = " << value << endl;
    }

    Prototype *clone() override {
        Prototype *instance = new ConcretePrototypeA();

        instance->setName(this->name);
        instance->setValue(this->value);

        return instance;
    }
};

class ConcretePrototypeB : public Prototype {
public:
    void printf() override {
        cout << "Concrete Prototype B!" << endl;
        cout << "Prototype name = " << name << endl;
        cout << "Prototype value = " << value << endl;
    }

    Prototype *clone() override {
        Prototype *instance = new ConcretePrototypeB();

        instance->setName(this->name);
        instance->setValue(this->value);

        return instance;
    }
};

void test01() {
    Prototype *A = new ConcretePrototypeA;
    Prototype *B = new ConcretePrototypeB;

    A->setValue(100);
    B->setName("Yui");

    Prototype *C = A->clone();
    Prototype *D = B->clone();

    C->printf();
    cout << "-----------------------" << endl;
    D->printf();
}

int main() {
    test01();
}
